// 铺垫1：十六进制（简写为hex或下标16）是一种基数为16的计数系统，是一种逢16进1的进位制。通常用数字0、1、2、3、4、5、6、7、8、9和字母A、B、C、D、E、F（a、b、c、d、e、f）表示，其中:A~F表示10~15，这些称作十六进制数字。
// 铺垫2：计算机信息都是0和1表示的也就是二进制，单对于人类来说二进制太长 -> 需要做精简，因此转化为十六进制 hexadecimal 简称 hex
// 铺垫3：在 C 语言中，十六进制数以”0x”或“0X”开头，A表示10，F表示16。
// 铺垫4：此后00000000~11111111就可以用0x00~0xFF来表示了。

// info函数第1个参数  domain：用于指定输出日志所对应的业务领域，取值范围为0x0000~0xFFFF，开发者可以根据需要进行自定义。 例如win蓝屏代码0x00000ffff是一个错误代码
// info函数第1个参数  tag：用于指定日志标识，可以为任意字符串，建议标识调用所在的类或者业务行为。tag最多为31字节，超出后会截断，不建议使用中文字符，可能出现乱码或者对齐问题。
// hilog.info(0xFF00, "slj", 'hello');
// hilog.info(0x0000, "slj", 'hello');

import { hilog } from "@kit.PerformanceAnalysisKit";

export interface LogOptionType {
  domain?: number
  tag?: string
  icon?: string,
  close?: boolean,
}

export class Log {
  private static option: LogOptionType = {
    domain: 0xFF00,
    tag: 'log',
    icon: '|',
    close: false,
  }

  static init(option: LogOptionType) {
    Object.assign(this.option, option)
  }

  static debug(data: any, tag?: string) {
    if (this.option.close) {
      return
    }
    hilog.debug(this.option.domain, tag || this.option.tag, this.format(data));
  }

  static info(data: any, tag?: string) {
    if (this.option.close) {
      return
    }
    hilog.info(this.option.domain, tag || this.option.tag, this.format(data));
  }

  static warn(data: any, tag?: string) {
    if (this.option.close) {
      return
    }
    hilog.warn(this.option.domain, tag || this.option.tag, this.format(data));
  }

  static error(data: any, tag?: string) {
    if (this.option.close) {
      return
    }
    hilog.error(this.option.domain, tag || this.option.tag, this.format(data));
  }

  static fatal(data: any, tag?: string) {
    if (this.option.close) {
      return
    }
    hilog.fatal(this.option.domain, tag || this.option.tag, this.format(data));
  }

  private static format(data: any): string {
    switch (typeof data) {
      case "object":
        if (data === null) {
          return null
        }
        return this.objToJson(data)
      case "string":
        if (data.startsWith("{") && data.endsWith("}")) {
          return this.objToJson(JSON.parse(data))
        } else {
          return data
        }
      default:
        return String(data)
    }
  }

  private static objToJson(data: object): string {
    return this.option.icon + " " + JSON.stringify(data, null, 2).replace(/\n/g, `\n${this.option.icon} `)
  }
}